package com.shangjinrong.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shangjinrong.domain.*;
import com.shangjinrong.domain.bo.TransFlowBO;
import com.shangjinrong.enums.LendStatusEnum;
import com.shangjinrong.enums.TransTypeEnum;
import com.shangjinrong.excption.Assert;
import com.shangjinrong.hfb.FormHelper;
import com.shangjinrong.hfb.HfbConst;
import com.shangjinrong.hfb.RequestHelper;
import com.shangjinrong.mapper.LendItemMapper;
import com.shangjinrong.mapper.LendMapper;
import com.shangjinrong.mapper.LendReturnMapper;
import com.shangjinrong.mapper.UserAccountMapper;
import com.shangjinrong.result.ResponseEnum;
import com.shangjinrong.service.LendItemReturnService;
import com.shangjinrong.service.LendReturnService;
import com.shangjinrong.service.TransFlowService;
import com.shangjinrong.service.UserBindService;
import com.shangjinrong.util.LendNoUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class LendReturnServiceImpl extends ServiceImpl<LendReturnMapper, LendReturn> implements LendReturnService {
    @Resource
    private UserAccountMapper userAccountMapper;

    @Resource
    private LendMapper lendMapper;

    @Resource
    private UserBindService userBindService;
    @Resource
    private LendItemReturnService lendItemReturnService;

    @Resource
    private TransFlowService transFlowService;

    @Resource
    private LendItemMapper lendItemMapper;

    @Override
    public List<LendReturn> getByLendId(Long id) {
        QueryWrapper<LendReturn> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("lend_id", id);

        List<LendReturn> lendReturnList = baseMapper.selectList(queryWrapper);

        return lendReturnList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String commitReturn(Long lendReturnId, Long userId) {

        //还款记录
        LendReturn lendReturn = baseMapper.selectById(lendReturnId);

        //获取用户余额
        QueryWrapper<UserAccount> userAccountQueryWrapper = new QueryWrapper<>();
        userAccountQueryWrapper.eq("user_id", userId);
        BigDecimal amount = userAccountMapper.selectOne(userAccountQueryWrapper).getAmount();

        //判断用户余额是否>=还款记录的本息
        Assert.isTrue(amount.doubleValue() >= lendReturn.getTotal().doubleValue(),
                ResponseEnum.NOT_SUFFICIENT_FUNDS_ERROR);

        //标的信息
        Lend lend = lendMapper.selectById(lendReturn.getLendId());

        //用户绑定协议号
        String bindCode = userBindService.getBindCodeByUserId(userId);

        Map<String, Object> paramMap = new HashMap<>();

        paramMap.put("agentId", HfbConst.AGENT_ID);
        paramMap.put("agentGoodsName", lend.getTitle());
        paramMap.put("agentBatchNo", lendReturn.getReturnNo());
        paramMap.put("fromBindCode", bindCode);
        paramMap.put("totalAmt", lendReturn.getTotal());
        paramMap.put("note", "");

        //还款明细
        List<Map<String, Object>> lendItemReturnDetailList = lendItemReturnService.addReturnDetail(lendReturnId);

        paramMap.put("data", JSON.toJSONString(lendItemReturnDetailList));

        paramMap.put("voteFeeAmt", new BigDecimal(0));
        paramMap.put("notifyUrl", HfbConst.BORROW_RETURN_NOTIFY_URL);
        paramMap.put("returnUrl", HfbConst.BORROW_RETURN_RETURN_URL);
        paramMap.put("timestamp", RequestHelper.getTimestamp());
        String sign = RequestHelper.getSign(paramMap);
        paramMap.put("sign", sign);

        String formStr = FormHelper.buildForm(HfbConst.BORROW_RETURN_URL, paramMap);
        return formStr;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void notify(Map<String, Object> paramMap) {
        log.info("还款成功");

        //还款编号
        String agentBatchNo = (String) paramMap.get("agentBatchNo");


        boolean result = transFlowService.isSaveTransFlow(agentBatchNo);

        //幂等性返回
        if (result) {
            log.warn("幂等性返回");
            return;
        }

        //获取还款数据
        QueryWrapper<LendReturn> lendReturnQueryWrapper = new QueryWrapper<>();
        lendReturnQueryWrapper.eq("return_no", agentBatchNo);

        LendReturn lendReturn = baseMapper.selectOne(lendReturnQueryWrapper);

        //更新还款状态
        lendReturn.setStatus((byte) 1);
        lendReturn.setFee(new BigDecimal(paramMap.get("voteFeeAmt").toString()));
        lendReturn.setReturnDate(new Date());
        baseMapper.updateById(lendReturn);

        //更新标的状态
        Lend lend = lendMapper.selectById(lendReturn.getLendId());

        //如果是最后一次还款，更改标的状态为已结清
        if (lendReturn.getIsLast()) {
            lend.setStatus(LendStatusEnum.PAY_OK.getCode().byteValue());
            lendMapper.updateById(lend);
        }

        //还款账号转出金额
        BigDecimal totalAmt = new BigDecimal(paramMap.get("totalAmt").toString());
        String bindCode = userBindService.getBindCodeByUserId(lendReturn.getUserId());
        userAccountMapper.updateAccount(bindCode, totalAmt.negate(), new BigDecimal(0));

        //还款交易流水
        TransFlowBO transFlowBO = new TransFlowBO(
                agentBatchNo,
                bindCode,
                totalAmt,
                TransTypeEnum.RETURN_DOWN,
                "借款人还款扣减，项目编号：" + lend.getLendNo() + "，项目名称：" + lend.getTitle());
        transFlowService.saveTransFlow(transFlowBO);

        List<LendItemReturn> lendItemReturnList = lendItemReturnService.selectLendItemReturnList(lendReturn.getId());

        lendItemReturnList.forEach(lendItemReturn -> {

            //更新回款状态
            lendItemReturn.setStatus((byte) 1);
            lendItemReturn.setRealReturnTime(new Date());
            lendItemReturnService.updateById(lendItemReturn);

            //更新投资记录
            LendItem lendItem = lendItemMapper.selectById(lendItemReturn.getLendItemId());
            //标的投资记录的预期收益会随着每一期的回款到账增加
            lendItem.setRealAmount(lendItem.getRealAmount().add(lendItemReturn.getInterest()));
            lendItemMapper.updateById(lendItem);


            //投资账号转入金额
            String investBindCode = userBindService.getBindCodeByUserId(lendItemReturn.getInvestUserId());
            userAccountMapper.updateAccount(investBindCode, lendItemReturn.getTotal(), new BigDecimal(0));

            //回款流水
            TransFlowBO investTransFlowBO = new TransFlowBO(
                    LendNoUtils.getReturnItemNo(),
                    investBindCode,
                    lendItemReturn.getTotal(),
                    TransTypeEnum.INVEST_BACK,
                    "还款到账，项目编号：" + lend.getLendNo() + "，项目名称：" + lend.getTitle()
            );

            transFlowService.saveTransFlow(investTransFlowBO);


        });
    }


}
